# COPYRIGHT BLABLA

import ogre.renderer.OGRE as ogre
import ogre.io.OIS as OIS

import os
import sys

class EventListener(OIS.MouseListener, OIS.KeyListener, OIS.JoyStickListener):
    mouse = None
    keyboard = None
    joy = None

    def __init__(self, wnd, mouse, key):
        OIS.MouseListener.__init__(self)
        OIS.KeyListener.__init__(self)
        OIS.JoyStickListener.__init__(self)
        self.KeyEvents = {}

        self.RenderWindow = wnd

        windowHnd = self.RenderWindow.getCustomAttributeInt('WINDOW')
        self.InputManager = OIS.createPythonInputSystem([('WINDOW', \
                str(windowHnd))])
        print dir(OIS)
        print "# mic: %s" % self.InputManager.getNumberOfDevices(OIS.OISJoyStick)
        try:
            if mouse:
                self.Mouse = self.InputManager.createInputObjectMouse(\
                        OIS.OISMouse, mouse)
                self.Mouse.setEventCallback(self)

            if key:
                self.Keyboard = self.InputManager.createInputObjectKeyboard(\
                        OIS.OISKeyboard, key)
                self.Keyboard.setEventCallback(self)

        except Exception, e:
            raise e

        self.QuiteApplication = False


    def __del__(self):
        self._del_input_objects()

        OIS.InputManager.destroyInputSystem(self.InputManager)
        self.InputManager = None

    def _del_input_objects(self):
        if self.Keyboard:
            self.InputManager.destroyInputObjectKeyboard(self.Keyboard)
        if self.Mouse:
            self.InputManager.destroyInputObjectMouse(self.Mouse)

    def set_window_resolution(self, width, height):
        if self.Mouse:
            st = self.Mouse.getMouseState()
            st.width = width
            st.height = height


    def update(self):
        if self.Keyboard:
            self.Keyboard.capture()
        if self.Mouse:
            self.Mouse.capture()
        
        return not self.QuiteApplication


    def mouseMoved(self, evt):
        # ADD TO GUI SYSTEM
#        s = evt.get_state()
#        print "X: %s, Y: %s, Z: %s, width: %s, height: %s" % (s.X.abs, s.Y.abs, s.Z.rel, s.width, s.height)
        return True

    def mousePressed(self, evt, id):
        # ADD TO GUI SYSTEM
        return True

    def mouseReleased(self, evt, id):
        # ADD TO GUI
        return True

    def keyPressed(self, evt):
        if self.KeyEvents.has_key(evt.key):
            self.KeyEvents[evt.key](True)

        return True

    def keyReleased(self, evt):
        if self.KeyEvents.has_key(evt.key):
            self.KeyEvents[evt.key](False)

        return True

    def register_key_event(self, key, method):
        self.KeyEvents[key] = method

    def unregister_key_event(self, key):
        if self.KeyEvents.has_key(key):
            self.KeyEvents.pop(key)


class OgreView(object):
    def __init__(self, title='Example...', fullscreen=False, \
            resolution=(1024, 768), resDir='media', \
            renderSystem=''):
        self.AppTitle = title
        self.Fullscreen = fullscreen
        self.ResourceDir = resDir
        self.RenderSystem = renderSystem
        self.Resolution = resolution

        self.Root = ogre.Root()
        self._setup_resources(self.ResourceDir)
        self._init_render_window()
        self._setup_scene()
        self.Timer = ogre.Timer()
        self.LastCnt = 0
        self.LastOffset = 0

        self.AnimationStates = {}

    def __del__(self):
        del self.Root


    def add_animation_state(self, state, speed):
        self.AnimationStates[state] = speed

    def remove_animation_state(self, state):
        if self.AnimationStates.has_key(state):
            self.AnimationStates.pop(state)

    def render(self):
        self.Root._fireFrameStarted()
        self.RenderWindow.update()
        self.Root._fireFrameRenderingQueued()
        self.Root._fireFrameEnded()

        offset = self.Timer.getMilliseconds()
        difference = offset - self.LastOffset
        self.LastOffset = offset

        for anim in self.AnimationStates.keys():
            anim.addTime(difference / 1000.0 * self.AnimationStates[anim])

        if offset > 5000:
            cnt = self.Root.getNextFrameNumber()
            print "Frames: %.2f" % ((cnt - self.LastCnt)/(offset/1000.0))
            self.LastCnt = cnt
            self.Timer.reset()

        return difference

    def _setup_resources(self, resDir):
        for root, lstDirs, lstFiles in os.walk(resDir):
            if ".svn" in lstDirs:
                lstDirs.remove('.svn')
            ogre.ResourceGroupManager.getSingleton().addResourceLocation(root,\
                    'FileSystem', 'General')
            for file in lstFiles:
                if file.lower().endswith('.zip'):
                    ogre.ResourceGroupManager.getSingleton().\
                            addResourceLocation(os.path.join(root, file), \
                                    'Zip', 'General')

    def _init_render_window(self):
        renderers = self.Root.getAvailableRenderers()

        if len(renderers) == 0:
            print "\n\nNO RENDERER AVAILABLE\n\n"
            sys.exit(-1)

        renderSystem = None
        for ren in renderers:
            if self.RenderSystem == ren.getName():
                renderSystem = ren
        if renderSystem is None:
            renderSystem = renderers[0]
        self.Root.setRenderSystem(renderSystem)
        if self.Fullscreen:
            renderSystem.setConfigOption("Full Screen", "Yes")
        else:
            renderSystem.setConfigOption("Full Screen", "No")
        renderSystem.setLightingEnabled(True)
        renderSystem.setShadingType(ogre.SO_FLAT)

        renderSystem.setConfigOption("Video Mode", "%s x  %s" % \
                self.Resolution)
 
        self.RenderWindow = self.Root.initialise(True, self.AppTitle)
        ogre.TextureManager.getSingleton().setDefaultNumMipmaps(5)
        ogre.ResourceGroupManager.getSingleton().initialiseAllResourceGroups()

    def _setup_scene(self, sceneManager=ogre.ST_GENERIC):
        self.SceneManager = self.Root.createSceneManager(sceneManager, \
                "Default SceneManager")
        self.Camera = self.SceneManager.createCamera("Camera")
        viewport = self.Root.getAutoCreatedWindow().addViewport(self.Camera)
        self.Camera.setNearClipDistance(1.0)
    

